/*
 * Copyright 2007 ZXing authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.google.zxing.datamatrix.decoder
{
	import com.google.zxing.ReaderException;
	/**
 * The Version object encapsulates attributes about a particular
 * size Data Matrix Code.
 *
 * @author bbrown@google.com (Brian Brown)
 */

	public class Version
    {
          private static  var VERSIONS:Array = buildVersions();
          private  var versionNumber:int;
          private  var symbolSizeRows:int;
          private  var symbolSizeColumns:int;
          private  var dataRegionSizeRows:int;
          private  var dataRegionSizeColumns:int;
          private  var ecBlocks:ECBlocks;
          private  var totalCodewords:int;

          public function Version(versionNumber:int,
                          symbolSizeRows:int,
                          symbolSizeColumns:int,
                          dataRegionSizeRows:int,
                          dataRegionSizeColumns:int,
                          ecBlocks:ECBlocks) {
            this.versionNumber = versionNumber;
            this.symbolSizeRows = symbolSizeRows;
            this.symbolSizeColumns = symbolSizeColumns;
            this.dataRegionSizeRows = dataRegionSizeRows;
            this.dataRegionSizeColumns = dataRegionSizeColumns;
            this.ecBlocks = ecBlocks;
            
            // Calculate the total number of codewords
            var total:int = 0;
            var ecCodewords:int = ecBlocks.getECCodewords();
            var ecbArray:Array = ecBlocks.getECBlocks();
            
            for (var i:int = 0; i < ecbArray.length; i++) 
            {
              var ecBlock:ECB = ecbArray[i];
              total += ecBlock.getCount() * (ecBlock.getDataCodewords() + ecCodewords);
            }
            
            this.totalCodewords = total;
          }

          public function getVersionNumber():int {
            return versionNumber;
          }

          public function getSymbolSizeRows():int {
            return symbolSizeRows;
          }
          
          public function getSymbolSizeColumns():int {
            return symbolSizeColumns;
          }
          
          public function getDataRegionSizeRows():int {
            return dataRegionSizeRows;
          }
          
          public function getDataRegionSizeColumns():int {
            return dataRegionSizeColumns;
          }
          
          public function getTotalCodewords():int {
            return totalCodewords;
          }
          
          public function getECBlocks():ECBlocks {
            return ecBlocks;
          }

          /**
           * <p>Deduces version information from Data Matrix dimensions.</p>
           *
           * @param numRows Number of rows in modules
           * @param numColumns Number of columns in modules
           * @return {@link Version} for a Data Matrix Code of those dimensions
           * @throws ReaderException if dimensions do correspond to a valid Data Matrix size
           */
          public static function getVersionForDimensions(numRows:int,numColumns:int):Version {
            if ((numRows & 0x01) != 0 || (numColumns & 0x01) != 0) {
              throw new ReaderException("Version : getVersionForDimensions : numColumns ("+numRows+") or numRows ("+numColumns+") uneven ");
            }
            
            // TODO(bbrown): This is doing a linear search through the array of versions.
            // If we interleave the rectangular versions with the square versions we could
            // do a binary search.
            var numVersions:int = VERSIONS.length;
            for (var i:int = 0; i < numVersions; ++i){
              var version:Version = VERSIONS[i];
              if (version.symbolSizeRows == numRows && version.symbolSizeColumns == numColumns) {
                return version;
              }
            }
            
            throw new ReaderException("Version : getVersionForDimensions : version could not be determined");
          }

          public function toString():String {
              return versionNumber.toString();
          }

          /**
           * See ISO 16022:2006 5.5.1 Table 7
           */
          private static function buildVersions():Array {
            return [
                new Version(1, 10, 10, 8, 8,
                    new ECBlocks(5, new ECB(1, 3))),
                new Version(2, 12, 12, 10, 10,
                    new ECBlocks(7, new ECB(1, 5))),
                new Version(3, 14, 14, 12, 12,
                    new ECBlocks(10, new ECB(1, 8))),
                new Version(4, 16, 16, 14, 14,
                    new ECBlocks(12, new ECB(1, 12))),
                new Version(5, 18, 18, 16, 16,
                    new ECBlocks(14, new ECB(1, 18))),
                new Version(6, 20, 20, 18, 18,
                    new ECBlocks(18, new ECB(1, 22))),
                new Version(7, 22, 22, 20, 20,
                    new ECBlocks(20, new ECB(1, 30))),
                new Version(8, 24, 24, 22, 22,
                    new ECBlocks(24, new ECB(1, 36))),
                new Version(9, 26, 26, 24, 24,
                    new ECBlocks(28, new ECB(1, 44))),
                new Version(10, 32, 32, 14, 14,
                    new ECBlocks(36, new ECB(1, 62))),
                new Version(11, 36, 36, 16, 16,
                    new ECBlocks(42, new ECB(1, 86))),
                new Version(12, 40, 40, 18, 18,
                    new ECBlocks(48, new ECB(1, 114))),
                new Version(13, 44, 44, 20, 20,
                    new ECBlocks(56, new ECB(1, 144))),
                new Version(14, 48, 48, 22, 22,
                    new ECBlocks(68, new ECB(1, 174))),
                new Version(15, 52, 52, 24, 24,
                    new ECBlocks(42, new ECB(2, 102))),
                new Version(16, 64, 64, 14, 14,
                    new ECBlocks(56, new ECB(2, 140))),
                new Version(17, 72, 72, 16, 16,
                    new ECBlocks(36, new ECB(4, 92))),
                new Version(18, 80, 80, 18, 18,
                    new ECBlocks(48, new ECB(4, 114))),
                new Version(19, 88, 88, 20, 20,
                    new ECBlocks(56, new ECB(4, 144))),
                new Version(20, 96, 96, 22, 22,
                    new ECBlocks(68, new ECB(4, 174))),
                new Version(21, 104, 104, 24, 24,
                    new ECBlocks(56, new ECB(6, 136))),
                new Version(22, 120, 120, 18, 18,
                    new ECBlocks(68, new ECB(6, 175))),
                new Version(23, 132, 132, 20, 20,
                    new ECBlocks(62, new ECB(8, 163))),
                new Version(24, 144, 144, 22, 22,
                    new ECBlocks(62, new ECB(8, 156), new ECB(2, 155))),
                new Version(25, 8, 18, 6, 16,
                    new ECBlocks(7, new ECB(1, 5))),
                new Version(26, 8, 32, 6, 14,
                    new ECBlocks(11, new ECB(1, 10))),
                new Version(27, 12, 26, 10, 24,
                    new ECBlocks(14, new ECB(1, 16))),
                new Version(28, 12, 36, 10, 16,
                    new ECBlocks(18, new ECB(1, 22))),
                new Version(29, 16, 36, 14, 16,
                    new ECBlocks(24, new ECB(1, 32))),
                new Version(30, 16, 48, 14, 22,
                    new ECBlocks(28, new ECB(1, 49)))];
            
          }
    }

}